#include "XMsgEvent.h"
#include "protobuf/xmsg_com.pb.h"
#include <event2/bufferevent.h>
#include <iostream>
#include <map>
#include "XTools.h"
using namespace std;
using namespace xmsg;
using namespace google;
using namespace protobuf;

static map<unsigned int, XMsgEvent::MsgCBFunc> cb_map;

void XMsgEvent::RegCB(int type, MsgCBFunc func)
{
    if (!cb_map.count(type))
        cb_map[type] = func;
    else
        XCOM_LOG_ERROR("RegCB type=" << type << " func is exist!");
}

void XMsgEvent::readCB()
{
    while (1)// 循环接收消息，但如果其他线程销毁了该连接，会出问题
    {
        if (!RecvMsg())
        {
            Clear();
            return;
        }

        auto msg = GetMsg();
        if (!msg)
        {
            Clear();
            return;
        }
        XCOM_LOG_DEBUG("service_name=" << pb_head_->service_name());
        readCB(pb_head_, msg);
        Clear();
    }
}

void XMsgEvent::readCB(xmsg::XMsgHead *head, XMsg *msg)
{
    if (!cb_map.count(msg->type))
    {
        XCOM_LOG_DEBUG("readCB type=" << msg->type << " func is not exist!");
        return;
    }

    (this->*cb_map[msg->type])(head, msg);
}

bool XMsgEvent::RecvMsg()
{
    if (!head_.size)
    {
        int len = Read(&head_.size, sizeof(head_.size));
        if (len <= 0 || head_.size <= 0)
            return false;

        if (!head_.Alloc(head_.size))
        {
            XCOM_ERROR_STREAM(cerr,"head_.Alloc failed!");
            return false;
        }
    }
    if (!head_.Recved())
    {
        int len = Read(
            head_.data + head_.recv_size,
            head_.size - head_.recv_size);
        if (len <= 0)
            return true;
        head_.recv_size += len;
        if (!head_.Recved())
            return true;

        if (!pb_head_)
        {
            pb_head_ = new XMsgHead();
        }
        if (!pb_head_->ParseFromArray(head_.data, head_.size))
        {
            XCOM_ERROR_STREAM(cerr,"pb_head_->ParseFromArray failed!");
            return false;
        }
        if(pb_head_->msg_size()==0){
            msg_.data=0;
        }
        else if (!msg_.Alloc(pb_head_->msg_size()))
        {
            XCOM_ERROR_STREAM(cerr,"msg_.Alloc failed!");
            return false;
        }
        msg_.type = pb_head_->msg_type();
    }
    if (!msg_.Recved())
    {
        int len = Read(
            msg_.data + msg_.recv_size,
            msg_.size - msg_.recv_size);
        if (len <= 0)
        {
            return true;
        }
        msg_.recv_size += len;
    }
    return true;
}

XMsg *XMsgEvent::GetMsg()
{
    if (msg_.Recved())
        return &msg_;
    return NULL;
}

void XMsgEvent::Clear()
{
    head_.Clear();
    msg_.Clear();
}

bool XMsgEvent::SendMsg(unsigned int type, const Message *message)
{
    if (!message)
        return false;

    XMsgHead head;
    head.set_msg_type(type);

    return SendMsg(&head, message);
}

bool XMsgEvent::SendMsg(xmsg::XMsgHead *head, const google::protobuf::Message *message)
{

    if (!message)
        return false;
    if (!head)
        return false;
    string msg_str = message->SerializeAsString();
    XMsg msg;
    msg.data = msg_str.data();
    msg.size = msg_str.size();
    msg.type = head->msg_type();
    return SendMsg(head, &msg);
}

bool XMsgEvent::SendMsg(xmsg::XMsgHead *head, XMsg *message)
{
    // 检查消息体是否为空，如果为空则返回false
    if (!message)
        return false;
    // 检查消息头是否为空，如果为空则返回false
    if (!head)
        return false;
    // 设置消息头的消息大小
    head->set_msg_size(message->size);

    // 序列化消息头为字符串
    string head_str = head->SerializeAsString();

    // 获取序列化消息头的大小
    int headsize = head_str.size();

    // 发送消息头的大小，如果发送失败则返回false
    bool ret = write(&headsize, sizeof(headsize));
    if (!ret)
        return false;

    // 发送序列化后的消息头，如果发送失败则返回false
    ret = write(head_str.data(), headsize);
    if (!ret)
        return false;

    // 发送消息体，如果发送失败则返回false
    ret = write(message->data, message->size);
    if (!ret)
        return false;

    // 如果所有部分都发送成功，则返回true
    return true;
}

bool XMsgEvent::Close()
{
    XMsgEvent::Clear();
    return XComTask::Close();
}
